package com.tticar.invmanager.service.impl;

import com.baomidou.mybatisplus.entity.Columns;
import com.baomidou.mybatisplus.mapper.Condition;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.tticar.invmanager.common.Enum.Status;
import com.tticar.invmanager.common.generator.FreemarkerEngine;
import com.tticar.invmanager.common.shiro.MySecurityUtils;
import com.tticar.invmanager.entity.SysDict;
import com.tticar.invmanager.entity.vo.DictCodes;
import com.tticar.invmanager.entity.vo.MyPage;
import com.tticar.invmanager.mapper.SysDictMapper;
import com.tticar.invmanager.service.ISysDictService;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 字典表 服务实现类
 * </p>
 *
 * @author joeyYan
 * @since 2018-07-08
 */
@Service
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements ISysDictService {

    @Override
    public Page selectPage(SysDict sysDict, MyPage<SysDict> page) {
        Wrapper<SysDict> wrapper = new EntityWrapper().orderBy(SysDict.SORT);
        wrapper.ne(Status.STATUS.getDesc(), Status.DELETE.getCode());
        Columns columns = Columns.create().column("*")
                .column("(select case count(1) when 0 then 'open' else 'closed' end from sys_dict t where t.pid=sys_dict.id)", "state");
        wrapper.setSqlSelect(columns);
        wrapper.eq(SysDict.PID, sysDict.getId());
        wrapper.like(Strings.isNotEmpty(sysDict.getName()), SysDict.NAME, sysDict.getName());
        wrapper.and(" (tenant_id={0} or (tenant_id=1 and editable=1)) ", MySecurityUtils.currentUser().getTenantId());
        return this.selectMapsPage(page, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> ids) {
        List list = new ArrayList();
        for (Long id : ids) {
            SysDict sysDict = new SysDict();
            sysDict.setId(id);
            //删除为-1，区分删除和禁用
            sysDict.setStatus(-1);
            list.add(sysDict);
        }
        this.updateBatchById(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SysDict sysDict) {
        this.insertOrUpdate(sysDict);
        if (StringUtils.isNotEmpty(sysDict.getCode())) {
            loadToLocal(); //
        }
    }

    @Override
    public Map loadForm(DictCodes dictCode) {
        Map map = new HashMap();
        List<Map> list = selTree(dictCode);
        for (int i = 0; i < list.size(); i++) {
            Map _map = list.get(i);
            if (_map.containsKey("children")) {
                list.addAll((List<Map>) _map.get("children"));
                continue;
            }
            map.put(MapUtils.getString(_map, SysDict.CODE), MapUtils.getString(_map, "id"));
        }
        return map;
    }

    @Override
    public synchronized void loadToLocal() {
        //
        Wrapper w = Condition.create();
        w.isNotNull(SysDict.CODE).addFilter(SysDict.CODE + " <> ''");
        List<SysDict> list = this.selectList(w);
        //
        Map<String, Integer> map = DictCodes.getMap();
        if (map == null) {
            DictCodes.setMap(new HashMap());
        } else {
            FreemarkerEngine.getInstance().put("sysDicts", list).writer();
        }
        DictCodes.getMap().clear();
        for (SysDict dict : list) {
            DictCodes.getMap().put(dict.getCode(), dict.getEditable());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void formSubmit(Map map) {
        SysDict dict = new SysDict();
        for (Object key : map.keySet()) {
            Object obj = map.get(key);
            if (obj != null && obj instanceof String[]) {
                dict.setValue(((String[]) obj)[0]);
            }
            this.update(dict, Condition.create().eq(SysDict.CODE, key));
        }
    }

    @Override
    public List selList(DictCodes dictCode) {
        Long[] tenants = new Long[]{MySecurityUtils.currentUser().getTenantId(), 1L};
        Wrapper ww = Condition.create().eq(SysDict.CODE, dictCode.toString());
        ww.in(dictCode.getEditable(), SysDict.TENANT_ID, tenants);
        SysDict sysDict = selectOne(ww);
        if (sysDict == null) {
            return new ArrayList();
        }
        Wrapper w = Condition.create().in(dictCode.getEditable(), SysDict.TENANT_ID, tenants);
        w.setSqlSelect(Columns.create().column(SysDict.VALUE).column(SysDict.VALUE, "id").column(SysDict.NAME, "text"));
        w.eq(SysDict.PID, sysDict.getId());
        w.eq(SysDict.STATUS, SysDict.ZERO);
        w.orderBy(SysDict.SORT);
        return this.selectMaps(w);
    }

    @Override
    public List selTree(DictCodes dictCode) {
        Long[] tenants = new Long[]{MySecurityUtils.currentUser().getTenantId(), 1l};
        Wrapper w = Condition.create();
        w.in(dictCode.getEditable(), SysDict.TENANT_ID, tenants).eq(SysDict.CODE, dictCode.toString());
        SysDict sysDict = selectOne(w);
        if (sysDict == null) {
            return new ArrayList();
        }
        return recursion(sysDict.getId(), dictCode.getEditable(), true);
    }

    public List recursion(Long id, boolean editable, boolean isFirst) {
        Long[] tenants = new Long[]{MySecurityUtils.currentUser().getTenantId(), 1l};
        Wrapper w = Condition.create();
        w.setSqlSelect(Columns.create().column(SysDict.CODE).column(SysDict.ID, "_id").column(SysDict.VALUE, "id").column(SysDict.NAME, "text"));
        w.eq(isFirst ? SysDict.ID : SysDict.PID, id);
        w.eq(SysDict.STATUS, SysDict.ZERO);
        w.in(editable, SysDict.TENANT_ID, tenants);
        w.orderBy(SysDict.SORT);
        List list = this.selectMaps(w);
        if (!list.isEmpty()) {
            for (Object o : list) {
                Long _id = MapUtils.getLong((Map) o, "_id");
                List _list = recursion(_id, editable, false);
                if (!_list.isEmpty()) {
                    ((Map) o).put("children", _list);
                }
            }
        }
        return list;
    }

    @Override
    public Map selMap(DictCodes dictCode) {
        List list = this.selList(dictCode);
        Map map = new HashMap();
        for (Object o : list) {
            Map _m = (Map) o;
            map.put(_m.get("_id"), _m.get("text"));
        }
        return map;
    }

}
